﻿using System;
using System.Linq.Expressions;
using System.Reflection;

namespace HossMvp.Core
{
    public class NameDecorator
    {
        public NameDecorator(string schema)
        {
            this.Schema = schema;
        }

        public string Schema { get; private set; }

        public string Decorate(string name)
        {
            if (name.Contains(".") == false)
            {
                name = this.Schema + "." + name;
            }

            return name;
        }

        public string NameOf<T>(Expression<Func<T, Func<ActionContext, ActionResult>>> expression)
        {
            if (expression == null) { throw new ArgumentNullException("expression"); }

            try
            {
                var body = (UnaryExpression)expression.Body;
                var operand = (MethodCallExpression)body.Operand;
                var obj = (ConstantExpression)operand.Object;
                var value = (MethodInfo)obj.Value;
                return value.Name;
            }
            catch (Exception x)
            {
                return x.Message;
            }
        }

        public string NameOf<T>(Expression<Func<T, Action<CommandContext>>> expression)
        {
            if (expression == null) { throw new ArgumentNullException("expression"); }

            try
            {
                var body = (UnaryExpression)expression.Body;
                var operand = (MethodCallExpression)body.Operand;
                var obj = (ConstantExpression)operand.Object;
                var value = (MethodInfo)obj.Value;
                return value.Name;
            }
            catch (Exception x)
            {
                return x.Message;
            }
        }

        public string NameOf<T>(Expression<Func<T, object>> expression)
        {
            if (expression == null) { throw new ArgumentNullException("expression"); }

            try
            {
                var body = (MemberExpression)expression.Body;
                var name = body.Member.Name;
                return name;
            }
            catch (Exception x)
            {
                return x.Message;
            }
        }
    }
}
